﻿
Imports System.Threading

Namespace destructor
    Public Module destructor
        Public Const maxDestructTime As UInt64 = 1000 * 60 * 16
        Public Const minDestructTime As UInt64 = 1000 * 7.5
        Public Const defaultDestructTime As UInt64 = 1000 * 60
        Public destructTime As UInt64 = defaultDestructTime
        Public Const defaultFullCollectRound As Int32 = 16
        Public fullCollectRound As Int32 = defaultFullCollectRound
        Friend destructThread As Thread = Nothing

        Public Sub destruct()
            GC.Collect()
        End Sub

        Friend Sub destructCaller()
            Try
#If Not (PocketPC OrElse Smartphone) Then
                Dim i As Int32 = 0
#End If
                While True
#If Not (PocketPC OrElse Smartphone) Then
                    If Environment.WorkingSet() >= (totalPhysicalMemory() >> 1) Then
                        destructTime >>= 2
                    ElseIf Environment.WorkingSet() >= (totalPhysicalMemory() >> 2) Then
                        destructTime >>= 1
                    ElseIf Environment.WorkingSet() < (totalPhysicalMemory() >> 6) Then
                        destructTime <<= 1
                    End If
#End If
                    If destructTime < minDestructTime Then
                        destructTime = minDestructTime
                    ElseIf destructTime > maxDestructTime Then
                        destructTime = maxDestructTime
                    End If
#If Not (PocketPC OrElse Smartphone) Then
                    i += 1
                    If i >= fullCollectRound Then
                        i = 0
                        'collect memory of non-refered objects in all generations
                        GC.Collect()
                    Else
                        'collect memory of non-refered objects in generations older than half of maxgeneration
                        GC.Collect(GC.MaxGeneration() >> 1)
                    End If
#Else
                    GC.Collect()
#End If
                    sleep(destructTime)
                End While
            Catch ex As ThreadAbortException
                raiseError("destructThread ended by ThreadAbortException.")
            Catch ex As Exception
                raiseError("unhandled exception in destructThread, ex " + ex.Message + ", callstack " + ex.StackTrace, _
                           errorHandle.errorType.critical)
            End Try
            destructThread = Nothing
        End Sub

        Public Sub start()
            If destructThread Is Nothing Then
                destructThread = New Thread(AddressOf destructCaller)
                destructThread.Start()
            End If
        End Sub

        Public Sub [stop]()
            On Error Resume Next

            If Not destructThread Is Nothing Then
#If Not (PocketPC OrElse Smartphone) Then
                If destructThread.IsAlive() Then
#End If
                    destructThread.Abort()
                    destructThread.Join()
#If Not (PocketPC OrElse Smartphone) Then
                End If
#End If
                destructThread = Nothing
            End If
        End Sub
    End Module
End Namespace
